#ifndef CYC_BASE_LOGSTREAM_H
#define CYC_BASE_LOGSTREAM_H

#include <string>
#include <string.h>

using std::string;

namespace cyc
{

  namespace detail
  {
    const int kTempBuffer = 512;
    const int kSmallBuffer = 4096;
    const int kLargeBuffer = 4096 * 1000;

    template <int SIZE>
    class FixedBuffer
    {
    public:
      FixedBuffer()
          : cur_(data_) {}

      ~FixedBuffer() {}

      void append(const char *buf, size_t len)
      {
        // FIXME: append partially,ensure have \0
        if (static_cast<size_t>(avail()) > len)
        {
          memcpy(cur_, buf, len);
          cur_ += len;
          *cur_ = '\0';
        }
      }

      const char *data() const { return data_; }
      int length() const { return static_cast<int>(cur_ - data_); }

      // count the least size,and leave '\n' and '\0'
      int avail() const { return static_cast<int>(end() - cur_ - 2); }

      void reset() { cur_ = data_; }

    private:
      const char *end() const { return data_ + sizeof data_; }

      char data_[SIZE];
      char *cur_;

    private:
      FixedBuffer(FixedBuffer &);
      FixedBuffer &operator=(FixedBuffer &);
    };
  }

  class LogStream
  {
  public:
    // 声明一个临时缓存的类型，kTempBuffer = 512.
    typedef detail::FixedBuffer<detail::kTempBuffer> Buffer;
    LogStream(void);
    ~LogStream(void);

    // 这里让他能接受各种基本参数
    LogStream &
    operator<<(short);
    LogStream &operator<<(unsigned short);
    LogStream &operator<<(int);
    LogStream &operator<<(unsigned int);
    LogStream &operator<<(long);
    LogStream &operator<<(unsigned long);
    LogStream &operator<<(long long);
    LogStream &operator<<(unsigned long long);

    LogStream &operator<<(const void *);

    LogStream &operator<<(float v)
    {
      *this << static_cast<double>(v);
      return *this;
    }
    LogStream &operator<<(double);

    // 本质就是，转化为字符，字符串类型，然后调用FixBuffer中的append()方法
    LogStream &
    operator<<(char v)
    {
      buffer_.append(&v, 1);
      return *this;
    }

    LogStream &operator<<(const char *v)
    {
      buffer_.append(v, strlen(v));
      return *this;
    }

    LogStream &operator<<(const string &v)
    {
      buffer_.append(v.c_str(), v.size());
      return *this;
    }

    void append(const char *data, int len) { buffer_.append(data, len); }
    const Buffer &buffer() const { return buffer_; }

  private:
    template <typename T>
    void formatInteger(T);

    Buffer buffer_;
    static const int kMaxNumericSize = 32;
  };
}

#endif // CYC_BASE_LOGSTREAM_H